package aiku.numericalcontroloa.Task;

import aiku.numericalcontroloa.Base.Utils.BaseEnum;
import aiku.numericalcontroloa.Mapper.*;
import aiku.numericalcontroloa.Mapper.DepartmentManagement.DepartmentMapper;
import aiku.numericalcontroloa.Mapper.DepartmentManagement.EmployeeDepartmentMapper;
import aiku.numericalcontroloa.Mapper.EmployeeAttendance.AttendanceMapper;
import aiku.numericalcontroloa.Mapper.EmployeeAttendance.ClockinRuleMapper;
import aiku.numericalcontroloa.Mapper.EmployeeAttendance.HolidaysMapper;
import aiku.numericalcontroloa.Mapper.MasterControl.MessageNotificationMapper;
import aiku.numericalcontroloa.Mapper.OrderManagement.OrderBillingMapper;
import aiku.numericalcontroloa.Mapper.OrderManagement.OrderMapper;
import aiku.numericalcontroloa.Model.Entity.*;
import aiku.numericalcontroloa.Model.Entity.Clock;
import aiku.numericalcontroloa.Model.Entity.DepartmentManagement.Department;
import aiku.numericalcontroloa.Model.Entity.DepartmentManagement.EmployeeDepartment;
import aiku.numericalcontroloa.Model.Entity.EmployeeAttendance.Attendance;
import aiku.numericalcontroloa.Model.Entity.EmployeeAttendance.ClockinRule;
import aiku.numericalcontroloa.Model.Entity.EmployeeAttendance.Holidays;
import aiku.numericalcontroloa.Model.Entity.MasterControl.MessageNotification;
import aiku.numericalcontroloa.Model.Entity.OrderManagement.Order;
import aiku.numericalcontroloa.Model.Entity.OrderManagement.OrderBilling;
import aiku.numericalcontroloa.Service.WorkSummaryService;
import aiku.numericalcontroloa.enums.RoleEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 定时任务
 * @Author 黄广庭
 * @Date 2024/4/26 16:47
 */
@Component
@EnableScheduling
public class ScheduledTask {

    @Autowired
    private HolidaysMapper holidaysMapper;
    @Autowired
    private AttendanceMapper attendanceMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ClockinRuleMapper clockinRuleMapper;
    @Autowired
    private EmployeeDepartmentMapper employeeDepartmentMapper;
    @Autowired
    private WorkSummaryMapper workSummaryMapper;
    @Autowired
    private UserScoreMapper userScoreMapper;
    @Autowired
    private WorkSummaryService workSummaryService;
    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private PurchaseOrdersMapper purchaseOrdersMapper;
    @Autowired
    private PaymentBillingMapper paymentBillingMapper;
    @Autowired
    private EmployeeProfileMapper employeeProfileMapper;
    @Autowired
    private MessageNotificationMapper msgNotificationMapper;
    @Autowired
    private ClockMapper clockMapper;
    @Autowired
    private ClientsMapper clientsMapper;
    @Autowired
    private CurrentMapper currentMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderBillingMapper orderBillingMapper;
    @Autowired
    private ChatMapper chatMapper;

    /**
     * 创建出勤记录任务
     * 创建员工打卡记录
     * 每天凌晨0点执行
     */
    @Scheduled(cron = "0 0 0 * * *")
    @Transactional
    public void createdAttendance(){
        try {
            System.out.println(">=============================================开始执行[创建出勤记录]任务=============================================<");
            LocalDate now = LocalDate.now();
            System.out.println("日期=========>"+now);
            // 查询假期表，获取节假日
            LambdaQueryWrapper<Holidays> holidaysLQW = new LambdaQueryWrapper<>();
            holidaysLQW.eq(Holidays::getYearValue, Year.now());
            Holidays holidays = holidaysMapper.selectOne(holidaysLQW);
            if (holidays == null){
                System.out.println(">----------------------------------未查询到节假日----------------------------------<");
                System.out.println(">=============================================任务[创建出勤记录]执行结束=============================================<");
                return;
            }
            // 判断今天是否是假期，为假期则结束定时任务
            String[] DateList = holidays.getDates().split(";");
            for (String date: DateList) {
                LocalDate localDate = LocalDate.parse(date);
                if (localDate.compareTo(now) == 0){
                    System.out.println(">-----------------------------------今日为节假日-----------------------------------<");
                    System.out.println(">=============================================任务[创建出勤记录]执行结束=============================================<");
                    return;
                }
            }

            // 查今天的出勤记录
            LambdaQueryWrapper<Attendance> attendanceLQW = new LambdaQueryWrapper<>();
            attendanceLQW.eq(Attendance::getClockingDate,now);
            List<Attendance> attendanceList = attendanceMapper.selectList(attendanceLQW);

            // 查询所有用户
            List<User> userList = userMapper.selectList(null);
            // 查询所有打卡规则
            List<ClockinRule> clockinRuleList = clockinRuleMapper.selectList(null);
            if (clockinRuleList.isEmpty()){
                // 打卡规则为空
                System.out.println(">=================================================未查询到打卡规则=================================================<");
                System.out.println(">=============================================任务[创建出勤记录]执行结束=============================================<");
                return;
            }
            // 处理成map，根据员工id获取打卡规则
            Map<String, ClockinRule> employeeClockinRuleMap = clockinRuleList.stream().filter(clockinRule -> clockinRule.getDepartmentId() == null)
                    .collect(Collectors.toMap(ClockinRule::getEmployeeId, Function.identity()));
            // 处理成map，根据部门id获取打卡规则
            Map<String, ClockinRule> departmentClockinRuleMap = clockinRuleList.stream().filter(clockinRule -> clockinRule.getEmployeeId() == null)
                    .collect(Collectors.toMap(ClockinRule::getDepartmentId, Function.identity()));

            // 查所有部门
            List<Department> departmentList = departmentMapper.selectList(null);
            Map<String, Department> departmentMap = departmentList.stream().collect(Collectors.toMap(Department::getId, Function.identity()));

            // 查员工部门
            List<EmployeeDepartment> employeeDepartmentList = employeeDepartmentMapper.selectList(null);
            // 处理成map，根据userId获取部门集合
            Map<String,List<EmployeeDepartment>> employeeDepartmentMap = new HashMap<>();
            for (EmployeeDepartment employeeDepartment : employeeDepartmentList){
                if (employeeDepartmentMap.containsKey(employeeDepartment.getEmployeeId())){
                    employeeDepartmentMap.get(employeeDepartment.getEmployeeId()).add(employeeDepartment);
                }else {
                    List<EmployeeDepartment> employeeDepartments = new ArrayList<>();
                    employeeDepartments.add(employeeDepartment);
                    employeeDepartmentMap.put(employeeDepartment.getEmployeeId(),employeeDepartments);
                }
            }

            // 创建出勤任务
            List<Attendance> attendances = new ArrayList<>();
            for (User user : userList) {
                // 判断用户是否有今日打卡记录
                boolean match = attendanceList.stream().anyMatch(item -> item.getEmployeeId().equals(user.getId()));
                if (match){
                    // 有打卡记录，跳过该用户
                    continue;
                }
                // 先查询个人打卡规则
                ClockinRule clockinRule = null;
                if (employeeClockinRuleMap.containsKey(user.getId())){
                    // 有个人打卡规则
                    clockinRule = employeeClockinRuleMap.get(user.getId());
                }else {
                    // 没有个人打卡规则，就查询部门打卡规则
                    // 查询个人加入的部门
                    if (!employeeDepartmentMap.containsKey(user.getId())){
                        // 未加入部门，跳过
                        continue;
                    }
                    List<EmployeeDepartment> employeeDepartments = employeeDepartmentMap.get(user.getId());
                    if (employeeDepartments.size() > 1){
                        // 加入的部门超过一个，跳过
                        continue;
                    }
                    EmployeeDepartment employeeDepartment = employeeDepartments.get(0);
                    if (!departmentClockinRuleMap.containsKey(employeeDepartment.getDepartmentId())){
                        // 没有该部门打卡规则，跳过
                        continue;
                    }
                    clockinRule = departmentClockinRuleMap.get(employeeDepartment.getDepartmentId());
//                    EmployeeDepartment employeeDepartment = employeeDepartments.get(0);
//                    Department department = departmentMap.get(employeeDepartment.getDepartmentId());
//                    clockinRule = getDepartmentClockinRule(departmentClockinRuleMap, departmentList, department);
                }
                if (clockinRule == null){
                    continue;
                }
                // 为用户创建出勤记录
                Attendance attendance = new Attendance();
                // 设置id
                attendance.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                // 设置打卡规则
                attendance.setClockinRuleId(clockinRule.getId());
                // 设置用户id
                attendance.setEmployeeId(user.getId());
                // 设置打卡日期
                attendance.setClockingDate(now);
                // 设置打卡类型为普通打卡
                attendance.setClockinType(0);
                // 设置创建时间
                attendance.setCreateTime(new Date());
                // 设置修改时间
                attendance.setUpdateTime(new Date());
                attendances.add(attendance);
            }
            // 更新数据
            if (attendances.size() > 0){
                attendanceMapper.insertBatch(attendances);
            }
            System.out.println(">=============================================任务[创建出勤记录]执行结束=============================================<");
        }catch (Exception e){
            e.printStackTrace();
            // 获取管理员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("任务执行失败");
                    // 内容
                    String content = "[创建出勤记录]任务执行失败，请联系技术人员进行修复";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    msg.setPublisherId(null);
                    // 接收人为管理员
                    msg.setReceiverId(user.getId());
                    // 没有类型
                    msg.setMsgType(0);
                    // 没有子菜单
                    msg.setSubmenu(0);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
    }

//    /**
//     * 获取部门打卡规则
//     * 传入的Department没有则查上级部门打卡规则
//     * 未获取到打卡规则返回null
//     * @param departmentClockinRuleMap 部门打卡规则Map
//     * @param departmentList 部门集合
//     * @param department 部门对象
//     * @return 打卡规则对象
//     */
//    public ClockinRule getDepartmentClockinRule(Map<String, ClockinRule> departmentClockinRuleMap,List<Department> departmentList,Department department){
//        if(departmentClockinRuleMap.containsKey(department.getId())){
//            // 有该部门的打卡规则
//            return departmentClockinRuleMap.get(department.getId());
//        }
//        // 没有该部门打卡规则，查上级部门
//        if (department.getParentDepartmentId() == null || department.getParentDepartmentId().isEmpty()){
//            // 上级部门为空，说明已是顶级部门，返回null
//            return null;
//        }
//        Optional<Department> result = departmentList.stream().filter(d -> d.getId().equals(department.getParentDepartmentId())).findFirst();
//        if (!result.isPresent()){
//            System.out.println("[ScheduledTask.getDepartmentClockinRule]:没有该上级部门(id: "+department.getParentDepartmentId()+")");
//            return null;
//        }
//        Department parentDepartment = result.get();
//        // 递归
//        return getDepartmentClockinRule(departmentClockinRuleMap,departmentList,parentDepartment);
//    }

    /**
     * 移动客户到公海池任务
     * 将业务员长时间未联系的客户移入公海池
     * 每天凌晨12点执行
     */
    @Scheduled(cron = "0 0 0 * * *")
    @Transactional
    public void moveClients(){
        try {

        }catch (Exception e){
            e.printStackTrace();
            // 获取管理员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("任务执行失败");
                    // 内容
                    String content = "[移动客户到公海池]任务执行失败，请联系技术人员进行修复";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    msg.setPublisherId(null);
                    // 接收人为管理员
                    msg.setReceiverId(user.getId());
                    // 没有类型
                    msg.setMsgType(0);
                    // 没有子菜单
                    msg.setSubmenu(0);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
        System.out.println(">=============================================开始执行[移动客户到公海池]任务=============================================<");
        // 查询联系天数
        Current current = currentMapper.selectById("2");
        // 获取今天日期
        LocalDate toDay = LocalDate.now();
        // 获取联系天数的日期
        LocalDate localDate = toDay.minusDays(current.getCourt());
        // 查所有的业务员
        LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
        userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                .eq(User::getRoleId,RoleEnum.ROLE_3.getCodeToString());
        List<User> userList = userMapper.selectList(userLQW);
        if (userList.isEmpty()){
            System.out.println(">======================================================无业务员======================================================<");
            System.out.println(">=============================================任务[移动客户到公海池]执行结束=============================================<");
            return;
        }
        // 查业务员的客户
        List<String> userIdList = userList.stream().map(User::getId).collect(Collectors.toList());
        LambdaQueryWrapper<Clients> clientsLQW = new LambdaQueryWrapper<>();
        clientsLQW.in(Clients::getSalesmanId,userIdList);
        List<Clients> clientsList = clientsMapper.selectList(clientsLQW);
        if (clientsList.isEmpty()){
            System.out.println(">=======================================================无客户=======================================================<");
            System.out.println(">=============================================任务[移动客户到公海池]执行结束=============================================<");
            return;
        }
        // 查客户交流记录
        List<String> clientIdList = clientsList.stream().map(Clients::getId).collect(Collectors.toList());
        LambdaQueryWrapper<Chat> chatLQW = new LambdaQueryWrapper<>();
        chatLQW.in(Chat::getClientsId,clientIdList);
        List<Chat> chatList = chatMapper.selectList(chatLQW);
        // 根据客户id获取交流对象
        Map<String,List<Chat>> chatMap = new HashMap<>();
        for (Chat chat : chatList){
            if (chatMap.containsKey(chat.getClientsId())){
                chatMap.get(chat.getClientsId()).add(chat);
            }else {
                List<Chat> chats = new ArrayList<>();
                chats.add(chat);
                chatMap.put(chat.getClientsId(),chats);
            }
        }
        List<Clients> moveClientList = new ArrayList<>();
        for (Clients clients : clientsList){
            List<Chat> chats = chatMap.get(clients.getId());
            // 按创建时间排序，时间最大的排最前面
            chats.sort((chat1, chat2) -> chat2.getCreateTime().compareTo(chat1.getCreateTime()));
            // 获取首个交流对象
            Chat chat = chats.get(0);
            // 首个交流对象的创建时间小于联系天数日期，则将该客户移入公海池
            LocalDate createTime = chat.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            if (createTime.compareTo(localDate) <= 0){
                // 添加到移入公海池列表
                moveClientList.add(clients);
            }
        }
        if (moveClientList.isEmpty()){
            // 无超过联系天数的客户
            System.out.println(">=================================================无超过联系天数的客户=================================================<");
            System.out.println(">=============================================任务[移动客户到公海池]执行结束=============================================<");
            return;
        }
        List<String> moveClientIdList = moveClientList.stream().map(Clients::getId).collect(Collectors.toList());
        LambdaUpdateWrapper<Clients> clientsUW = new LambdaUpdateWrapper<>();
        clientsUW.in(Clients::getId,moveClientIdList).set(Clients::getSalesmanId,null);
        clientsMapper.update(null,clientsUW);
        // 创建消息通知
        List<MessageNotification> msgList = new ArrayList<>();
        for (Clients clients : moveClientList){
            MessageNotification msg = new MessageNotification();
            msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
            // 标题
            msg.setTitle("自动放弃客户提醒");
            // 内容
            String content = "您超过"+current.getCourt()+"天未与客户("+clients.getName()+")联系，已自动放弃该客户";
            msg.setContent(content);
            // 发布人，系统通知
            msg.setPublisherId(null);
            // 接收人，业务员
            msg.setReceiverId(clients.getSalesmanId());
            // 类型为客户管理
            msg.setMsgType(4);
            // 子菜单为1客户列表
            msg.setSubmenu(1);
            // 状态为待处理
            msg.setStatus(0);
            msg.setCreateTime(new Date());
            msgList.add(msg);
        }
        msgNotificationMapper.insertBatch(msgList);
        System.out.println(">=============================================任务[移动客户到公海池]执行结束=============================================<");
    }

    /**
     * 更新用户平均分
     * 每天晚上23:58执行
     * @return
     */
    @Scheduled(cron = "0 58 23 * * *")
    @Transactional
    public void updateUserScore() {
        try {
            System.out.println(">=============================================开始执行[更新用户平均分]任务=============================================<");
            LocalDate today = LocalDate.now();
            LocalDateTime startDateTime = LocalDateTime.of(today, LocalTime.MIN);
            LocalDateTime endDateTime = LocalDateTime.of(today, LocalTime.MAX);

            //查询所有用户当天的记录
            LambdaQueryWrapper<WorkSummary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.between(WorkSummary::getWorkTime,startDateTime,endDateTime);
            List<WorkSummary> workSummaries = workSummaryMapper.selectList(queryWrapper);
            List<String> workIdList = new ArrayList<>();
            Map<String, WorkSummary> workSummaryMap = new HashMap<>();
            if (workSummaries.isEmpty()){
                workIdList.add("");
            }else {
                workIdList = workSummaries.stream().map(WorkSummary::getWorkId).collect(Collectors.toList());
                workSummaryMap = workSummaries.stream().collect(Collectors.toMap(WorkSummary::getWorkId, Function.identity()));
            }
            //通过id去查询大家评分记录表
            List<UserScore> userScoreList = userScoreMapper.selectList(new LambdaQueryWrapper<UserScore>().in(UserScore::getWorkId, workIdList));
            for (Map.Entry<String, WorkSummary> entry : workSummaryMap.entrySet()) {
                String key = entry.getKey();
                //总分数,总人数
                Integer score = 0;
                for (UserScore userScore : userScoreList) {
                    if (userScore.getWorkId().equals(key)){
                        score+=userScore.getScore();
                    }
                }
                entry.getValue().setScore(score);
            }
            //转换成list集合,并且更新
            List<WorkSummary> workSummaryList = workSummaryMap.values().stream().collect(Collectors.toList());
            workSummaryService.updateBatchById(workSummaryList);
            System.out.println(">=============================================任务[更新用户平均分]执行结束=============================================<");
        }catch (Exception e){
            e.printStackTrace();
            // 获取管理员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("任务执行失败");
                    // 内容
                    String content = "[更新用户平均分]任务执行失败，请联系技术人员进行修复";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    msg.setPublisherId(null);
                    // 接收人为管理员
                    msg.setReceiverId(user.getId());
                    // 没有类型
                    msg.setMsgType(0);
                    // 没有子菜单
                    msg.setSubmenu(0);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
    }

    /**
     * 月结账单提醒
     */
    @Scheduled(cron = "0 0 0 * * *")
    @Transactional
    public void surplusRemind(){
        try {
            System.out.println(">=============================================开始执行[月结账单提醒]任务=============================================<");
            // 查询本月未付款账单
            // 获取当前月
            YearMonth currMonth = YearMonth.now();
            LambdaQueryWrapper<PaymentBilling> paymentBillingLQW = new LambdaQueryWrapper<>();
            paymentBillingLQW.ne(PaymentBilling::getBillsStatus,1)
                    .apply("DATE_FORMAT(date_payable, '%Y-%m') = {0}",currMonth);
            List<PaymentBilling> billingList = paymentBillingMapper.selectList(paymentBillingLQW);
            if (billingList.isEmpty()){
                System.out.println(">===================================================没有付款账单===================================================<");
                System.out.println(">=============================================任务[月结账单提醒]执行结束=============================================<");
                return;
            }
            // 根据采购订单id获取采购账单
            Map<String, PaymentBilling> billingMap = billingList.stream().collect(Collectors.toMap(PaymentBilling::getOrderId, Function.identity()));
            List<String> orderIdList = billingList.stream().map(PaymentBilling::getOrderId).collect(Collectors.toList());
            // 查采购订单
            LambdaQueryWrapper<PurchaseOrders> purchaseOrdersLQW = new LambdaQueryWrapper<>();
            // 结款方式为月结
            purchaseOrdersLQW.eq(PurchaseOrders::getPaymentMethod,1).in(PurchaseOrders::getId,orderIdList);
            List<PurchaseOrders> purchaseOrdersList = purchaseOrdersMapper.selectList(purchaseOrdersLQW);
            if (purchaseOrdersList.isEmpty()){
                System.out.println(">===================================================没有月结账单===================================================<");
                System.out.println(">=============================================任务[月结账单提醒]执行结束=============================================<");
                return;
            }
            // 获取供应商id
            Set<String> suppliersIdList = purchaseOrdersList.stream().map(PurchaseOrders::getSuppliersId).collect(Collectors.toSet());
            // 获取财务员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_6.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("供应商月结提醒");
                    // 内容
                    String content = "有"+suppliersIdList.size()+"家供应商有月结账单待付款";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    // 接收人为财务员
                    msg.setReceiverId(user.getId());
                    // 类型为仓库管理
                    msg.setMsgType(6);
                    // 子菜单为6供应商管理
                    msg.setSubmenu(6);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
            System.out.println(">=============================================任务[月结账单提醒]执行结束=============================================<");
        }catch (Exception e){
            e.printStackTrace();
            // 获取管理员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("任务执行失败");
                    // 内容
                    String content = "[月结账单提醒]任务执行失败，请联系技术人员进行修复";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    msg.setPublisherId(null);
                    // 接收人为管理员
                    msg.setReceiverId(user.getId());
                    // 没有类型
                    msg.setMsgType(0);
                    // 没有子菜单
                    msg.setSubmenu(0);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
    }

    /**
     * 月结账单转月结余
     * 每月的第一天0点执行
     */
    @Scheduled(cron = "0 0 0 1 * *")
    @Transactional
    public void supplierSurplus(){
        try {
            System.out.println(">=============================================开始执行[月结账单转月结余]任务=============================================<");
            // 查询上个月未付款的账单
            // 获取当前月
            YearMonth currMonth = YearMonth.now();
            // 获取上个月的年月
            YearMonth prevMonth = currMonth.minusMonths(1);
            LambdaQueryWrapper<PaymentBilling> paymentBillingLQW = new LambdaQueryWrapper<>();
            paymentBillingLQW.ne(PaymentBilling::getBillsStatus,1)
                    .apply("DATE_FORMAT(date_payable, '%Y-%m') = {0}",prevMonth);
            List<PaymentBilling> billingList = paymentBillingMapper.selectList(paymentBillingLQW);
            Map<String, PaymentBilling> billingMap = billingList.stream().collect(Collectors.toMap(PaymentBilling::getOrderId, Function.identity()));
            List<String> orderIdList = billingList.stream().map(PaymentBilling::getOrderId).collect(Collectors.toList());
            // 查采购订单
            LambdaQueryWrapper<PurchaseOrders> purchaseOrdersLQW = new LambdaQueryWrapper<>();
            // 结款方式为月结
            purchaseOrdersLQW.eq(PurchaseOrders::getPaymentMethod,1).in(PurchaseOrders::getId,orderIdList);
            List<PurchaseOrders> purchaseOrdersList = purchaseOrdersMapper.selectList(purchaseOrdersLQW);
            if (purchaseOrdersList.isEmpty()){
                // 没有月结账单
                System.out.println(">====================================================没有月结账单=====================================================<");
                System.out.println(">=============================================任务[月结账单转月结余]执行结束=============================================<");
                return;
            }
            // 更新应付日期
            List<PaymentBilling> paymentBillingList = new ArrayList<>();
            for (PurchaseOrders purchaseOrder : purchaseOrdersList){
                // 设置应付日期
                // 本月最后一天
                LocalDate currentDate = LocalDate.now();
                LocalDate lastDayOfMonth = currentDate.withDayOfMonth(currentDate.lengthOfMonth());
                PaymentBilling paymentBilling = billingMap.get(purchaseOrder.getId());
                paymentBilling.setDatePayable(lastDayOfMonth);
                paymentBillingList.add(paymentBilling);
            }
            paymentBillingMapper.updateBatchById(paymentBillingList);
            System.out.println(">=============================================任务[月结账单转月结余]执行结束=============================================<");
        }catch (Exception e){
            e.printStackTrace();
            // 获取管理员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("任务执行失败");
                    // 内容
                    String content = "[月结账单转月结余]任务执行失败，请联系技术人员进行修复";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    msg.setPublisherId(null);
                    // 接收人为管理员
                    msg.setReceiverId(user.getId());
                    // 没有类型
                    msg.setMsgType(0);
                    // 没有子菜单
                    msg.setSubmenu(0);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
    }

    /**
     * 合同到期提醒
     * 每天凌晨执行
     */
    @Scheduled(cron = "0 0 0 * * *")
    @Transactional
    public void profileExpire(){
        try {
            System.out.println(">=============================================执行开始[合同到期提醒]任务=============================================<");
            // 获取今天日期
            LocalDate today = LocalDate.now();
            // 根据今天日期查询职工档案
            LambdaQueryWrapper<EmployeeProfile> employeeProfileLQW = new LambdaQueryWrapper<>();
            employeeProfileLQW.eq(EmployeeProfile::getEmployeeContractRemindDate,today);
            List<EmployeeProfile> employeeProfileList = employeeProfileMapper.selectList(employeeProfileLQW);
            if (employeeProfileList.isEmpty()){
                System.out.println(">====================================================无到期合同===================================================<");
                System.out.println(">=============================================任务[合同到期提醒]执行结束=============================================<");
                return;
            }
            List<MessageNotification> msgList = new ArrayList<>();
            for (EmployeeProfile employeeProfile : employeeProfileList){
                // 创建消息记录
                MessageNotification msg = new MessageNotification();
                msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                // 标题
                msg.setTitle("合同到期提醒");
                // 内容为合同到期日期
                LocalDate contractDate = employeeProfile.getEmployeeContractDate();
                String content = "您的合同将于一个月后("+contractDate.getYear()+"年"+contractDate.getMonthValue()+"月"+contractDate.getDayOfMonth()+"日)到期";
                msg.setContent(content);
                // 发布人为null，系统通知
                // 接收人为合同到期员工
                msg.setReceiverId(employeeProfile.getUserId());
                // 类型为职工档案
                msg.setMsgType(2);
                // 子菜单为1档案管理
                msg.setSubmenu(1);
                // 状态为待处理
                msg.setStatus(0);
                msg.setCreateTime(new Date());
                msgList.add(msg);
            }
            msgNotificationMapper.insertBatch(msgList);
            System.out.println(">=============================================任务[合同到期提醒]执行结束=============================================<");
        }catch (Exception e){
            e.printStackTrace();
            // 获取管理员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("任务执行失败");
                    // 内容
                    String content = "[合同到期提醒]任务执行失败，请联系技术人员进行修复";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    msg.setPublisherId(null);
                    // 接收人为管理员
                    msg.setReceiverId(user.getId());
                    // 没有类型
                    msg.setMsgType(0);
                    // 没有子菜单
                    msg.setSubmenu(0);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
    }

    /**
     * 客户约谈时间提醒
     * 每天凌晨执行
     */
    @Scheduled(cron = "0 0 0 * * *")
    @Transactional
    public void remindTime(){
        try {
            System.out.println(">=============================================执行开始[客户约谈时间提醒]任务=============================================<");
            // 获取今天日期
            LocalDate today = LocalDate.now();
            // 根据今天日期查询clock表
            LambdaQueryWrapper<Clock> clockLQW = new LambdaQueryWrapper<>();
            clockLQW.apply("DATE_FORMAT(remind_time, '%Y-%m') = {0}",today);
            List<Clock> todayClockList = clockMapper.selectList(clockLQW);
            // 获取明天的日期
            LocalDate tomorrow = today.plusDays(1);
            // 根据明天日期查询clock表
            clockLQW = new LambdaQueryWrapper<>();
            clockLQW.apply("DATE_FORMAT(remind_time, '%Y-%m') = {0}",tomorrow);
            List<Clock> tomorrowClockList = clockMapper.selectList(clockLQW);

            List<MessageNotification> msgList = new ArrayList<>();
            if (!todayClockList.isEmpty()){
                // 查客户
                Set<String> clientsIdList = todayClockList.stream().map(Clock::getClientsId).collect(Collectors.toSet());
                List<Clients> clientsList = clientsMapper.selectBatchByIdWithDelete(clientsIdList);
                Map<String, Clients> clientsMap = clientsList.stream().collect(Collectors.toMap(Clients::getId, Function.identity()));
                for (Clock clock : todayClockList) {
                    Clients clients = clientsMap.get(clock.getClientsId());
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("客户交流提醒");
                    // 内容
                    String content = "今天是您与客户（"+clients.getName()+"）约谈的日期";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    // 接收人为业务员
                    msg.setReceiverId(clock.getRemindUserId());
                    // 关联id
                    msg.setRelevanceId(clock.getClientsId());
                    // 类型为客户管理
                    msg.setMsgType(4);
                    // 子菜单为1客户列表
                    msg.setSubmenu(1);
                    // 状态为待处理
                    msg.setStatus(0);
                    msgList.add(msg);
                }
            }
            if (!tomorrowClockList.isEmpty()){
                Set<String> clientsIdList = tomorrowClockList.stream().map(Clock::getClientsId).collect(Collectors.toSet());
                List<Clients> clientsList = clientsMapper.selectBatchByIdWithDelete(clientsIdList);
                Map<String, Clients> clientsMap = clientsList.stream().collect(Collectors.toMap(Clients::getId, Function.identity()));
                for (Clock clock : tomorrowClockList){
                    Clients clients = clientsMap.get(clock.getClientsId());
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("客户交流提醒");
                    // 内容
                    String content = "明天是您与客户（"+clients.getName()+"）约谈的日期";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    // 接收人为业务员
                    msg.setReceiverId(clock.getRemindUserId());
                    // 关联id
                    msg.setRelevanceId(clock.getClientsId());
                    // 类型为客户管理
                    msg.setMsgType(4);
                    // 子菜单为1客户列表
                    msg.setSubmenu(1);
                    // 状态为待处理
                    msg.setStatus(0);
                    msgList.add(msg);
                }
            }
            if (!msgList.isEmpty()){
                msgNotificationMapper.insertBatch(msgList);
            }
            System.out.println(">=============================================任务[客户约谈时间提醒]执行结束=============================================<");
        }catch (Exception e){
            e.printStackTrace();
            // 获取管理员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("任务执行失败");
                    // 内容
                    String content = "[客户约谈时间提醒]任务执行失败，请联系技术人员进行修复";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    msg.setPublisherId(null);
                    // 接收人为管理员
                    msg.setReceiverId(user.getId());
                    // 没有类型
                    msg.setMsgType(0);
                    // 没有子菜单
                    msg.setSubmenu(0);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
    }

    /**
     * 还款日到期提醒
     * 每天凌晨执行
     */
    @Scheduled(cron = "0 0 0 * * *")
    @Transactional
    public void repaymentReminderDays(){
        try {
            System.out.println(">=============================================开始执行[还款日到期提醒]任务=============================================<");
            // 查询提醒日期
            Current current = currentMapper.selectById("3");
            // 获取今天日期
            LocalDate toDay = LocalDate.now();
            // 获取提醒天数日期
            LocalDate reminderDays = toDay.plusDays(current.getCourt());
            // 查询订单账单
            LambdaQueryWrapper<OrderBilling> orderBillingLQW = new LambdaQueryWrapper<>();
            orderBillingLQW.eq(OrderBilling::getRepaymentDate,reminderDays)
                    .eq(OrderBilling::getBillStatus,0);
            List<OrderBilling> orderBillingList = orderBillingMapper.selectList(orderBillingLQW);
            if (orderBillingList.isEmpty()){
                System.out.println(">====================================================没有还款账单===================================================<");
                System.out.println(">=============================================任务[还款日到期提醒]执行结束=============================================<");
                return;
            }
            // 查询订单列表
            Set<String> orderIdList = orderBillingList.stream().map(OrderBilling::getOrderId).collect(Collectors.toSet());
            List<Order> orderList = orderMapper.selectBatchIdWithDelete(orderIdList, 0);
            orderList.addAll(orderMapper.selectBatchIdWithDelete(orderIdList, 2));
            Map<String, Order> orderMap = orderList.stream().collect(Collectors.toMap(Order::getId, Function.identity()));
            Set<String> clientsIdList = orderList.stream().map(Order::getClientsId).collect(Collectors.toSet());
            List<Clients> clientsList = clientsMapper.selectBatchByIdWithDelete(clientsIdList);
            // 根据id获取客户对象
            Map<String, Clients> clientsMap = clientsList.stream().collect(Collectors.toMap(Clients::getId,Function.identity()));
            List<MessageNotification> msgList = new ArrayList<>();
            for (OrderBilling orderBilling : orderBillingList){
                // 创建消息通知
                MessageNotification msg = new MessageNotification();
                msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                // 标题
                msg.setTitle("收款日到期提醒");
                // 内容
                Order order = orderMap.get(orderBilling.getOrderId());
                Clients clients = clientsMap.get(order.getClientsId());
                int monthValue = orderBilling.getRepaymentDate().getMonthValue();
                int dayOfMonth = orderBilling.getRepaymentDate().getDayOfMonth();
                String content = clients.getName()+"距离还款日还有"+current.getCourt()+"天("+monthValue+"月"+dayOfMonth+"日)";
                msg.setContent(content);
                // 发布人为null，系统通知
                // 接收人为要提醒的业务员
                msg.setReceiverId(order.getUserId());
                // 关联id
                msg.setRelevanceId(orderBilling.getId());
                // 类型为订单管理
                msg.setMsgType(5);
                // 子菜单为1订单列表
                msg.setSubmenu(1);
                // 状态为待处理
                msg.setStatus(0);
                msg.setCreateTime(new Date());
                msgList.add(msg);
            }
            msgNotificationMapper.insertBatch(msgList);
            System.out.println(">=============================================任务[还款日到期提醒]执行结束=============================================<");
        }catch (Exception e){
            e.printStackTrace();
            // 获取管理员
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt())
                    .eq(User::getRoleId, RoleEnum.ROLE_1.getCodeToString());
            List<User> userList = userMapper.selectList(userLQW);
            if (!userList.isEmpty()){
                List<MessageNotification> msgList = new ArrayList<>();
                for (User user : userList){
                    // 创建消息通知
                    MessageNotification msg = new MessageNotification();
                    msg.setId(UUID.randomUUID().toString().replaceAll("-",""));
                    // 标题
                    msg.setTitle("任务执行失败");
                    // 内容
                    String content = "[还款日到期提醒]任务执行失败，请联系技术人员进行修复";
                    msg.setContent(content);
                    // 发布人为null，系统通知
                    msg.setPublisherId(null);
                    // 接收人为管理员
                    msg.setReceiverId(user.getId());
                    // 没有类型
                    msg.setMsgType(0);
                    // 没有子菜单
                    msg.setSubmenu(0);
                    // 状态为待处理
                    msg.setStatus(0);
                    msg.setCreateTime(new Date());
                    msgList.add(msg);
                }
                msgNotificationMapper.insertBatch(msgList);
            }
        }
    }
}
